/**
 *
 */
package name.yzhu.wbdata.io;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import name.yzhu.common.Constant;
import name.yzhu.common.io.BinaryFileWriter;
import name.yzhu.common.io.FileIndexEntry;
import name.yzhu.common.util.IdentifyUnique;
import name.yzhu.common.yaml.YamlItem;
import name.yzhu.wbdata.WBDataUtil;

/**
 * @author yhzhu
 *
 */
public class PersistYaml implements IPersistWeibo {
	private static final Log LOG = LogFactory.getLog(PersistYaml.class);
	private File output = null;
	private OutputStream writer = null;
	BinaryFileWriter index = new BinaryFileWriter();
	private long currentOff = 0;
	private IdentifyUnique identifyUnique = null;

	public PersistYaml(String out, IdentifyUnique identify) {
		this(new File(out));
		setIdentifyUniqueue(identify);
	}

	public PersistYaml(final File out) {
		output = out;
	}

	public void open() throws IOException{
		try {
			if (output.exists())
				currentOff  = FileUtils.sizeOf(output);
			if (!output.getParentFile().exists())
				FileUtils.forceMkdir(output.getParentFile());
			writer  = new BufferedOutputStream(
							new FileOutputStream(output, true), 64*name.yzhu.common.Constant.NUM_1K);
			index.open(output.getAbsolutePath()+Constant.IDX_FILE_SUFFIX_NAEM);

		} catch (FileNotFoundException e) {
			LOG.error("open file failed "+output.getAbsolutePath(), e);
			throw new IOException(e);
		} catch (IOException e) {
			LOG.error("open file failed "+output.getAbsolutePath(), e);
			throw new IOException(e);
		}
	}

	public void close() throws IOException{
		try {
			if (writer != null){
				writer.close();
			    writer = null;
			}
			if (index != null){
				index.close();
				index = null;
			}
		} catch (IOException e) {
			throw new IOException(e);
		}
	}
	/* (non-Javadoc)
	 * @see name.yzhu.wbdata.weibo.IPersistStatus#persist(java.util.List, name.yzhu.wbdata.weibo.AbstractTimeLine.TimeLineType)
	 */
	@Override
	public void persistYaml(List<YamlItem> ymals)
			throws IOException {

		for (YamlItem yaml : ymals){
			try{
			   persistYaml(yaml);
			}
			catch(Exception e){
				LOG.error(e.getMessage(), e);
			}
		}

		writer.flush();
	}

	@Override
	public void persistYaml(final YamlItem yaml) throws IOException {
		String uuid = yaml.getString(Constant.YAML_FIELD_UUID);
		if (uuid == null){
			uuid = WBDataUtil.getUUID(yaml.getString(name.yzhu.common.Constant.YAML_FIELD_DATA_SOURCE),
	    			String.valueOf(yaml.get(
	    					name.yzhu.wbdata.Constant.YAML_FIELD_WEIBO_ID)));
	    	yaml.put(name.yzhu.common.Constant.YAML_FIELD_UUID, uuid);
		}

		try {
		    if (!identifyUnique.contain(uuid)){
				byte[] buf = yaml.getRaw();
				writer.write(buf);
				FileIndexEntry idx = new FileIndexEntry();
				idx.setId(String.valueOf(yaml.get("id")));
				idx.setOffset(currentOff);
				idx.setLength(buf.length);
				index.write(idx);
				currentOff += buf.length;
		    }
		    else {
		    	LOG.warn("skipping duplicated: "+uuid+
		    			" data_source: "+yaml.getString(Constant.YAML_FIELD_DATA_SOURCE+
		    			" id: "+String.valueOf(yaml.get(name.yzhu.wbdata.Constant.YAML_FIELD_WEIBO_ID))));
		    }
		} catch (Exception e) {
			String err="skipping duplicated: "+uuid+
			" data_source: "+yaml.getString(Constant.YAML_FIELD_DATA_SOURCE+
	    			" id: "+String.valueOf(yaml.get(name.yzhu.wbdata.Constant.YAML_FIELD_WEIBO_ID)));
			LOG.error("persist failed "+err, e);
			throw new IOException(err, e);
		}
	}

	@Override
	public void setIdentifyUniqueue(IdentifyUnique identify) {
		this.identifyUnique  = identify;
	}
}
